package ar.activity;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
import ar.Location.Helper.CalculationProvider;
import ar.Location.PlaceObject.PlaceCategory;
import ar.Location.TextToSpeak.TTSHelper;
import ar.camera.glsurfaceview.extend.RouteSurfaceView;
import ar.camera.pojo.GLLocation;
import ar.camera.pojo.GeoLocation;
import ar.camera.surfaceview.CameraSurfaceView;
import ar.camera.thread.RouteUIThread;
import ar.globals.Globals;
import ar.sensor.SensorListener;
import ar.utils.LocationUtils;

public class ARRouteActivity extends Activity {
	RouteSurfaceView view;
	CameraSurfaceView camView;

	private SensorManager mSensorManager;
	private SensorListener mSensorListener;
	// Sensor accelerometer;
	// Sensor magnetometer;
	// Sensor orientator;

	private float lastCompassAzimut = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		mSensorListener = new SensorListener();
		mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		// accelerometer = mSensorManager
		// .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		// magnetometer = mSensorManager
		// .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
		// orientator =
		// mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

		view = new RouteSurfaceView(this);
		Globals.routeOriginGeo = Globals.currentGeoLocation;

		addContentView(view, new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));

		camView = new CameraSurfaceView(this, 0);
		addContentView(camView, new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));

		LayoutInflater inflater = (LayoutInflater) this
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout = inflater.inflate(R.layout.route_camera, null, false);
		addContentView(layout, new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT));
	}

	@Override
	protected void onPause() {
		super.onPause();
		view.onPause();
		mSensorManager.unregisterListener(mSensorListener);
	}

	@Override
	protected void onResume() {
		super.onResume();
		view.onResume();
		// mSensorManager.registerListener(mSensorListener, accelerometer,
		// SensorManager.SENSOR_DELAY_UI);
		// mSensorManager.registerListener(mSensorListener, magnetometer,
		// SensorManager.SENSOR_DELAY_UI);
		// mSensorManager.registerListener(mSensorListener, orientator,
		// SensorManager.SENSOR_DELAY_UI);

		Globals.isFinishedARRoute = false;
		final ImageView iv = (ImageView) findViewById(R.id.ivRouteCompass);
		Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case Globals.UPDATE_ROUTE_COMPASS:
					RotateAnimation rotateAnimation = new RotateAnimation(
							lastCompassAzimut, -Globals.routeAzimut,
							Animation.RELATIVE_TO_SELF, 0.5f,
							Animation.RELATIVE_TO_SELF, 0.5f);
					rotateAnimation.setInterpolator(new LinearInterpolator());
					rotateAnimation.setDuration(0);
					rotateAnimation.setFillAfter(true);
					iv.startAnimation(rotateAnimation);

					lastCompassAzimut = -Globals.routeAzimut;

					updateInfo();
					break;

				default:
					break;
				}
			}
		};

		RouteUIThread tr = new RouteUIThread(handler, this);
		Thread t = new Thread(tr);
		t.start();
	}

	@Override
	protected void onStop() {
		super.onStop();
	}

	public void updateInfo() {

		Display display = getWindowManager().getDefaultDisplay();
		int compensation = display.getRotation();
		Log.v("compensation", String.valueOf(compensation));

		for (int i = 0; i < Globals.listOfRoutePoints.size(); i++) {
			if (Globals.listOfRoutePoints.get(i).mLatitude == 0
					&& Globals.listOfRoutePoints.get(i).mLongitude == 0) {
				Globals.listOfRoutePoints.remove(i);
				i--;
			}
		}

		GLLocation originGL = LocationUtils
				.convertFromGeoLocationToGLLocation(Globals.routeOriginGeo);
		List<GeoLocation> geos = new ArrayList<GeoLocation>();
		for (int i = 0; i < Globals.listOfRoutePoints.size(); i++) {
			GeoLocation g = new GeoLocation(
					Globals.listOfRoutePoints.get(i).mLatitude,
					Globals.listOfRoutePoints.get(i).mLongitude, "");
			geos.add(g);
		}
		List<GLLocation> listLcts = LocationUtils
				.convertFromListOfGeoLocationsToListOfGLLocations(geos,
						Globals.routeOriginGeo, 1000);
		GLLocation currentGL = LocationUtils
				.convertFromGeoLocationToGLLocation(Globals.currentGeoLocation);
		currentGL.x = (currentGL.x - originGL.x) * 500000;
		currentGL.z = (currentGL.z - originGL.z) * 500000;

		if (Globals.listOfRoutePoints != null
				&& Globals.listOfRoutePoints.size() < 2)
			return;
		int index1 = 0;
		int index2 = 1;
		float area = -1;
		for (int i = 0; i < listLcts.size() - 1; i++) {
			GLLocation l0 = listLcts.get(i);
			GLLocation l1 = listLcts.get(i + 1);
			float ang1 = calcAngleBetween2Vector(currentGL, l0, l1);
			float ang2 = calcAngleBetween2Vector(currentGL, l1, l0);
			if (ang1 < 90 && ang2 < 90) {
				float arTmp = calcArea(l0, l1, currentGL);
				if (area == -1)
					area = arTmp;
				if (arTmp < area) {
					index1 = i;
					index2 = i + 1;
				}
			}
		}

		final float stepDis = CalculationProvider.distFrom(
				Globals.currentGeoLocation.latitude,
				Globals.currentGeoLocation.longitude,
				Globals.listOfRoutePoints.get(index2).mLatitude,
				Globals.listOfRoutePoints.get(index2).mLongitude);
		TextView tvRouteStepDis = (TextView) findViewById(R.id.tvRouteStepDis);
		tvRouteStepDis.setText(String.valueOf(Math.round(stepDis)));
		tvRouteStepDis.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				TTSHelper.doSpeak(String.valueOf(Math.round(stepDis)));				
			}
		});

		float totalDis = 0;
		totalDis += stepDis;
		for (int i = index2; i < Globals.listOfRoutePoints.size() - 1; i++) {
			float dis = CalculationProvider.distFrom(
					Globals.listOfRoutePoints.get(i).mLatitude,
					Globals.listOfRoutePoints.get(i).mLongitude,
					Globals.listOfRoutePoints.get(i + 1).mLatitude,
					Globals.listOfRoutePoints.get(i + 1).mLongitude);
			totalDis += dis;
		}
		final TextView tvRouteTotalDis = (TextView) findViewById(R.id.tvRouteTotalDis);
		tvRouteTotalDis.setText(String.valueOf(Math.round(totalDis)));
		tvRouteTotalDis.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				TTSHelper.doSpeak(tvRouteTotalDis.getText().toString());				
			}
		});

		final TextView tvRouteGoal = (TextView) findViewById(R.id.tvRouteGoal);
		tvRouteGoal.setText(PlaceCategory.currentPlace.name);
		tvRouteGoal.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				TTSHelper.doSpeak(tvRouteGoal.getText().toString());	
			}
		});

		final TextView tvRouteInfo = (TextView) findViewById(R.id.tvRouteInfo);
		tvRouteInfo.setText(Globals.listOfRoutePoints.get(index1).mName
				+ "\nThen, "
				+ Globals.listOfRoutePoints.get(index2).mDescription);
		tvRouteInfo.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				TTSHelper.doSpeak(tvRouteInfo.getText().toString());
				
			}
		});
		// atan2(v2.y,v2.x) - atan2(v1.y,v1.x)
		// float alpha = (float) (Math.atan2(l2.x - l1.x, l2.z - l1.z) -
		// Math.atan2(0, -1f));
		ImageView ivRouteDirection = (ImageView) findViewById(R.id.ivRouteDirection);
		ivRouteDirection.setImageResource(R.drawable.straight);
		if (index2 + 1 < Globals.listOfRoutePoints.size()) {
			// currentGL
			GLLocation l1 = listLcts.get(index2);
			GLLocation l2 = listLcts.get(index2 + 1);
			float alpha = (float) (Math.atan2(l2.x - l1.x, l2.z - l1.z) - Math
					.atan2(currentGL.x - l1.x, currentGL.z - l1.z));
			if ((alpha >= Math.PI / 3 && alpha <= 5 * Math.PI / 6)
					|| (alpha >= -5 * Math.PI / 3 && alpha <= -7 * Math.PI / 6)) {
				ivRouteDirection.setImageResource(R.drawable.turn_right);
			}
			if ((alpha >= 7 * Math.PI / 6 && alpha <= 5 * Math.PI / 3)
					|| (alpha >= -5 * Math.PI / 6 && alpha <= -Math.PI / 3)) {
				ivRouteDirection.setImageResource(R.drawable.turn_left);
			}
			if ((alpha >= 0 && alpha <= Math.PI / 3)
					|| (alpha >= -2 * Math.PI && alpha <= -5 * Math.PI / 3)) {
				ivRouteDirection.setImageResource(R.drawable.turn_right_around);
			}
			if ((alpha >= 5 * Math.PI / 3 && alpha <= 2 * Math.PI)
					|| (alpha >= -Math.PI / 3 && alpha <= 0)) {
				ivRouteDirection.setImageResource(R.drawable.turn_left_around);
			}

		}
		// }
	}

	public float calcAngleBetween2Vector(GLLocation l0, GLLocation l1,
			GLLocation l2) {
		if (l0.x == l1.x && l0.z == l1.z)
			return 0;
		if (l0.x == l2.x && l0.z == l2.z)
			return 0;

		float angle = 0;
		float tmp1 = (l0.x - l1.x) * (l2.x - l1.x) + (l0.z - l1.z)
				* (l2.z - l1.z);
		float tmp2 = (float) Math.sqrt((l0.x - l1.x) * (l0.x - l1.x)
				+ (l0.z - l1.z) * (l0.z - l1.z));
		float tmp3 = (float) Math.sqrt((l2.x - l1.x) * (l2.x - l1.x)
				+ (l2.z - l1.z) * (l2.z - l1.z));

		angle = (float) Math.acos(tmp1 / tmp2 / tmp3);
		return (float) (angle * 180 / Math.PI);
	}

	public float calcArea(GLLocation l0, GLLocation l1, GLLocation l2) {
		float area = 0;
		float a = (float) Math.sqrt((l0.x - l1.x) * (l0.x - l1.x)
				+ (l0.z - l1.z) * (l0.z - l1.z));
		float b = (float) Math.sqrt((l2.x - l1.x) * (l2.x - l1.x)
				+ (l2.z - l1.z) * (l2.z - l1.z));
		float c = (float) Math.sqrt((l2.x - l0.x) * (l2.x - l0.x)
				+ (l2.z - l0.z) * (l2.z - l0.z));
		float p = (a + b + c) / 2;

		area = (float) Math.sqrt(p * (p - a) * (p - b) * (p - c));

		return area;
	}

	@Override
	public void onBackPressed() {
		super.onBackPressed();

		if (camView != null) {
			if (camView.camera != null) {
				camView.releaseCam();
			}
		}
		Globals.isFinishedARRoute = true;
		finish();
	}
}